﻿using Swashbuckle.Swagger;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web.Http.Description;

namespace SingleUserMall.Web.Filters
{
    public class DocumentFilter : IDocumentFilter
    {
        private string AbpPath = "AbpCache|AbpServiceProxies|app/session|app/tenant|ServiceProxies|TypeScript";
        private string hackcontrollername(string name)
        {
            //return name;
            if (name.Contains('_'))
            {
                return name.Replace("_", "/");
            }
            else
            {
                return name;
            }
        }
        public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
        {
            //隐藏文档
            foreach (var apiDescription in apiExplorer.ApiDescriptions)
            {
                //hide attr
                var HideAbpAutogeneratedApi = true;
                var HideDocPaths = new string[] { };
                var HideDocPathAttributeName = "";
                //remove from docs autogenerated services
                if (HideAbpAutogeneratedApi)
                {
                    Regex r = new Regex(AbpPath);
                    if (r.IsMatch(apiDescription.ID))
                    {
                        swaggerDoc.paths.Remove("/" + apiDescription.RelativePath.Split('?')[0]);
                        continue;
                    }

                }
                if (HideDocPaths != null && HideDocPaths.Length > 0)
                {
                    if (HideDocPaths.Where(p => apiDescription.ID.Contains(p)).Count() > 0)
                    {
                        swaggerDoc.paths.Remove("/" + apiDescription.RelativePath.Split('?')[0]);
                        continue;
                    }
                }
                if (!string.IsNullOrEmpty(HideDocPathAttributeName))
                {
                    var attr = apiDescription.GetControllerAndActionAttributes<object>();
                    if (attr != null && attr.Where(p => p.ToString() == HideDocPathAttributeName).Count() > 0)
                    {
                        swaggerDoc.paths.Remove("/" + apiDescription.RelativePath.Split('?')[0]);
                        continue;
                    }
                }
            }

            //添加Tag`
            swaggerDoc.tags = new List<Tag>();
            var controllers = apiExplorer.ApiDescriptions.Select(p => p.ActionDescriptor.ControllerDescriptor).Distinct();
            foreach (var item in controllers)
            {
                item.ControllerName = hackcontrollername(item.ControllerName);
                var name = item.ControllerName;
                var type = item.ControllerType?.GenericTypeArguments?.FirstOrDefault();
                if (type == null) continue;
                var attrs = type.GetCustomAttributes(false);
                var desc = attrs.Where(i => i is DisplayNameAttribute).ToList();
                if (desc != null && desc.Count > 0)
                {
                    //hack
                    swaggerDoc.tags.Add(new Tag() { name = name, description = (desc[0] as DisplayNameAttribute).DisplayName });
                }
                else
                {
                    //var desc2 = item.GetCustomAttributes<DescriptionAttribute>();
                    var desc2 = attrs.Where(i => i is DescriptionAttribute).ToList();
                    if (desc2 != null && desc2.Count > 0)
                    {
                        swaggerDoc.tags.Add(new Tag() { name = name, description = (desc2[0] as DescriptionAttribute).Description });
                    }
                }
            }
            swaggerDoc.tags = swaggerDoc.tags.OrderBy(x => x.name).ToList();

            //优化枚举显示
            foreach (var schemaDictionaryItem in swaggerDoc.definitions)
            {
                var schema = schemaDictionaryItem.Value;
                foreach (var propertyDictionaryItem in schema.properties)
                {
                    var property = propertyDictionaryItem.Value;
                    var propertyEnums = property.@enum;
                    if (propertyEnums != null && propertyEnums.Count > 0)
                    {
                        var enumDescriptions = new List<string>();
                        for (int i = 0; i < propertyEnums.Count; i++)
                        {
                            var enumOption = propertyEnums[i];
                            var desc = (DisplayAttribute)enumOption.GetType().GetField(enumOption.ToString()).GetCustomAttributes(true).Where(p => p is DisplayAttribute).FirstOrDefault();
                            if (desc == null)
                            {
                                enumDescriptions.Add(string.Format("{0} = {1} ", Convert.ToInt32(enumOption), Enum.GetName(enumOption.GetType(), enumOption)));
                            }
                            else
                            {
                                enumDescriptions.Add(string.Format("{0} = {1} ", Convert.ToInt32(enumOption), desc.Name));
                            }

                        }
                        property.description += string.Format(" ({0})", string.Join(", ", enumDescriptions.ToArray()));
                    }
                }
            }
        }
    }
}
